package com.srmt.document.feishu.internal.table.impl;

import com.lark.oapi.service.docx.v1.model.Block;
import com.lark.oapi.service.docx.v1.model.TableMergeInfo;
import com.lark.oapi.service.docx.v1.model.UpdateBlockRequest;
import com.srmt.document.exception.TableException;
import com.srmt.document.feishu.internal.table.TableOperationStrategy;
import com.srmt.document.feishu.internal.table.TableReadStrategy;
import com.srmt.document.feishu.internal.table.TableWriteStrategy;
import com.srmt.document.feishu.internal.table.TableStructureStrategy;
import com.srmt.document.feishu.internal.table.model.TableContext;
import com.srmt.document.feishu.internal.table.model.TableType;
import com.srmt.document.model.RowData;
import com.srmt.document.model.TableData;
import com.srmt.feishu.client.FeishuClient;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 表格操作策略抽象基类
 * 
 * 提供表格操作的共享基础实现，
 * 具体的表格类型策略可以继承此类并重写特定方法。
 * 
 * 现在同时实现新的细粒度接口和原有的TableOperationStrategy接口，
 * 以保持向后兼容。
 * 
 * @author srmt
 * @since 3.0.0
 */
public abstract class AbstractTableStrategy implements TableOperationStrategy, 
                                                       TableReadStrategy, 
                                                       TableWriteStrategy, 
                                                       TableStructureStrategy {
    
    protected static final Logger logger = LoggerFactory.getLogger(AbstractTableStrategy.class);
    
    protected final FeishuClient client;
    protected final TableType tableType;
    
    /**
     * 构造抽象策略
     * 
     * @param client 飞书客户端
     * @param tableType 表格类型
     */
    protected AbstractTableStrategy(FeishuClient client, TableType tableType) {
        if (client == null) {
            throw new IllegalArgumentException("客户端不能为null");
        }
        if (tableType == null) {
            throw new IllegalArgumentException("表格类型不能为null");
        }
        this.client = client;
        this.tableType = tableType;
    }
    
    @Override
    public TableType getTableType() {
        return tableType;
    }
    
    @Override
    public boolean supportsBlockType(int blockType) {
        return blockType == tableType.getBlockType();
    }
    
    @Override
    public boolean validateTableOperation(TableContext context) {
        if (context == null) {
            logger.error("表格上下文为null");
            return false;
        }
        
        if (context.getTableBlock() == null) {
            logger.error("表格块为null");
            return false;
        }
        
        if (context.getTableType() != tableType) {
            logger.error("表格类型不匹配: 期望{}, 实际{}", 
                        tableType, context.getTableType());
            return false;
        }
        
        return true;
    }
    
    @Override
    public String getDescription() {
        return String.format("%s Strategy (blockType=%d)", 
                           tableType.getDescription(), 
                           tableType.getBlockType());
    }
    
    // ========== 共享的工具方法 ==========
    
    /**
     * 生成唯一的Block ID
     * 
     * @param prefix ID前缀
     * @return 唯一的Block ID
     */
    protected String generateBlockId(String prefix) {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return prefix + "_" + uuid.substring(0, 16);
    }
    
    /**
     * 生成等宽的列宽数组
     * 
     * @param cols 列数
     * @return 列宽数组
     */
    protected Integer[] generateEqualWidth(int cols) {
        if (cols <= 0) {
            return new Integer[0];
        }
        
        int totalWidth = 5000; // 飞书表格总宽度
        int columnWidth = totalWidth / cols;
        Integer[] widths = new Integer[cols];
        
        for (int i = 0; i < cols; i++) {
            widths[i] = columnWidth;
        }
        
        // 将剩余宽度加到最后一列
        int remainder = totalWidth - (columnWidth * cols);
        if (remainder > 0 && cols > 0) {
            widths[cols - 1] += remainder;
        }
        
        return widths;
    }
    
    /**
     * 验证行列索引
     * 
     * @param row 行索引
     * @param col 列索引
     * @param maxRow 最大行数
     * @param maxCol 最大列数
     * @throws TableException 如果索引无效
     */
    protected void validateCellIndex(int row, int col, int maxRow, int maxCol) 
            throws TableException {
        if (row < 0 || row >= maxRow) {
            throw new TableException(String.format(
                "Row index out of bounds: %d (max: %d)", row, maxRow - 1));
        }
        if (col < 0 || col >= maxCol) {
            throw new TableException(String.format(
                "Column index out of bounds: %d (max: %d)", col, maxCol - 1));
        }
    }
    
    /**
     * 验证表格维度
     * 
     * @param rows 行数
     * @param cols 列数
     * @throws IllegalArgumentException 如果维度无效
     */
    protected void validateTableDimensions(int rows, int cols) {
        if (rows <= 0) {
            throw new IllegalArgumentException("Number of rows must be positive, got: " + rows);
        }
        if (cols <= 0) {
            throw new IllegalArgumentException("Number of columns must be positive, got: " + cols);
        }
        
        // 飞书表格限制
        if (rows > 500) {
            throw new IllegalArgumentException("Number of rows exceeds maximum (500), got: " + rows);
        }
        if (cols > 20) {
            throw new IllegalArgumentException("Number of columns exceeds maximum (20), got: " + cols);
        }
    }
    
    /**
     * 计算单元格在一维数组中的索引
     * 
     * @param row 行索引
     * @param col 列索引
     * @param columnCount 总列数
     * @return 一维数组索引
     */
    protected int calculateCellIndex(int row, int col, int columnCount) {
        return row * columnCount + col;
    }
    
    // ========== 默认实现（子类可以覆盖） ==========
    
    @Override
    public int[] findCellWithText(TableContext context, String text) throws TableException {
        if (!validateTableOperation(context)) {
            throw new TableException("表格上下文无效");
        }
        
        if (text == null || text.isEmpty()) {
            return null;
        }
        
        int[] dimensions = getTableDimensions(context);
        int rows = dimensions[0];
        int cols = dimensions[1];
        
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                String content = getCellContent(context, row, col);
                if (content != null && content.contains(text)) {
                    logger.debug("在单元格[{}, {}]找到文本'{}'", row, col, text);
                    return new int[]{row, col};
                }
            }
        }
        
        return null;
    }
    
    @Override
    public boolean isMergedCell(TableContext context, int row, int col) throws TableException {
        TableMergeInfo[] mergeInfo = getTableMergeInfo(context);
        if (mergeInfo == null) {
            return false;
        }
        row--;
        col--;
        int[] dimensions = getTableDimensions(context);
        int columnCount = dimensions[1];
        int cellIndex = calculateCellIndex(row, col, columnCount);
        
        if (cellIndex >= mergeInfo.length) {
            return false;
        }
        
        TableMergeInfo merge = mergeInfo[cellIndex];
        if (merge == null) {
            return false;
        }
        
        // rowSpan或colSpan大于1表示是合并单元格的起始单元格
        // rowSpan或colSpan等于0表示是被合并的单元格
        return (merge.getRowSpan() > 1 || merge.getColSpan() > 1) ||
               (merge.getRowSpan() == 0 || merge.getColSpan() == 0);
    }
    
    @Override
    public int[] getCellSpan(TableContext context, int row, int col) throws TableException {
        row--;
        col--;
        TableMergeInfo[] mergeInfo = getTableMergeInfo(context);
        if (mergeInfo == null) {
            return new int[]{1, 1};
        }
        
        int[] dimensions = getTableDimensions(context);
        int columnCount = dimensions[1];
        int cellIndex = calculateCellIndex(row, col, columnCount);
        
        if (cellIndex >= mergeInfo.length) {
            return new int[]{1, 1};
        }
        
        TableMergeInfo merge = mergeInfo[cellIndex];
        if (merge == null) {
            return new int[]{1, 1};
        }
        
        int rowSpan = merge.getRowSpan() > 0 ? merge.getRowSpan() : 1;
        int colSpan = merge.getColSpan() > 0 ? merge.getColSpan() : 1;
        
        return new int[]{rowSpan, colSpan};
    }
    
    // ========== 单元格内容更新操作（默认实现） ==========
    
    @Override
    public void updateCellContentByIndex(TableContext context, int row, int col, String value) 
            throws TableException {
        // 默认实现：抛出不支持异常，子类需要覆盖
        throw new TableException(String.format(
            "Updating cell content is not yet implemented for %s table type", 
            getTableType().name()));
    }
    
    @Override
    public void batchUpdateCellsByIndex(TableContext context, Map<int[], String> cellUpdates) 
            throws TableException {
        // 默认实现：逐个调用单元格更新
        if (cellUpdates == null || cellUpdates.isEmpty()) {
            return;
        }
        
        for (Map.Entry<int[], String> entry : cellUpdates.entrySet()) {
            int[] position = entry.getKey();
            if (position != null && position.length >= 2) {
                updateCellContentByIndex(context, position[0], position[1], entry.getValue());
            }
        }
    }
    
    // ========== 单元格合并操作（默认实现） ==========
    
    @Override
    public void mergeCells(TableContext context, int startRow, int startCol, 
                          int endRow, int endCol) throws TableException {
        // 默认实现：抛出不支持异常，子类可以覆盖
        throw new TableException(String.format(
            "%s类型的表格不支持合并单元格",
            getTableType().name()));
    }
    
    @Override
    public void unmergeCells(TableContext context, int startRow, int startCol,
                            int endRow, int endCol) throws TableException {
        // 默认实现：抛出不支持异常，子类可以覆盖
        throw new TableException(String.format(
            "%s类型的表格不支持取消合并单元格",
            getTableType().name()));
    }
    
    // ========== 未实现的方法（子类必须实现） ==========
    
    // 以下方法留给具体策略实现，因为不同表格类型有不同的实现方式
    // 子类需要根据具体的表格类型提供实现
}